package rise.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;

import org.apache.http.conn.util.InetAddressUtils;
import org.osmdroid.tileprovider.modules.INetworkAvailablityCheck;

import rise.comunity.Community;
import rise.comunity.UserData;
import rise.message.Login;
import rise.message.Packet;
import rise.message.Registration;
import rise.ui.AccessActivity;
import rise.ui.Splash;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public abstract class SenderTask extends AsyncTask<Void, Void, Integer> {
	private String packetRappresentation;
	private Context context;
	private final String failureMessage = "Errore di connessione.";
	private LocationManager locationManager;
	private LocationListener locationListener;
	private boolean requiresResponse = false;

	protected static Socket socket;
	protected PrintWriter printWriter;
	protected BufferedReader bufferedReader;

	protected SenderTask(Packet packet, Context context) {

		try {
			locationManager = (LocationManager) context
					.getSystemService(Context.LOCATION_SERVICE);
			locationListener = new LocationListener() {
				public void onLocationChanged(Location loc) {
				}

				public void onStatusChanged(String provider, int status,
						Bundle extras) {
				}

				public void onProviderEnabled(String provider) {
				}

				public void onProviderDisabled(String provider) {
				}
			};
			Location lastLocation = this.getGPSLocation();
			packet.setLat(lastLocation.getLatitude());
			packet.setLon(lastLocation.getLongitude());
		} catch (Exception e) {
			packet.setLat(0);
			packet.setLon(0);
		}

		this.packetRappresentation = packet.toXML();
		this.context = context;

		if (packet instanceof Login || packet instanceof Registration)
			requiresResponse = true;
	}

	private Location getGPSLocation() throws Exception {
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
				0, locationListener);
		Location lastLocation = locationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);

		if (lastLocation == null)
			throw new Exception();

		return lastLocation;
	}

	private void setUpSocket() throws UnknownHostException, IOException {
		UserData userData = UserData.obtainUserData();
		if (userData == null && socket == null) {
			Log.e("-", "1");
			socket = new Socket(ServerConnection.getAddress(),
					ServerConnection.getServerPort());
			printWriter = new PrintWriter(socket.getOutputStream());
			bufferedReader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
		} else if (userData == null && socket != null) {
			printWriter = new PrintWriter(socket.getOutputStream());
			bufferedReader = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
		} else if (userData != null && socket != null && userData.existSocket()) {
			Log.e("-", "3");
			printWriter = userData.getPrintWriter();
			bufferedReader = userData.getBufferedReader();
		} else {
			Log.e("-", "???");
		}


	}

	@Override
	protected Integer doInBackground(Void... params) {
		int response = 0;
		try {
			response = this._doInBackgroud();
			if (response == Packet.UNKNOWN_PACKET)
				return this.handleInvalidPacket();
		} catch (SocketException e) {
			return this.handleServerUnreachable();
		} catch (IOException e) {
			return this.handleServerUnreachable();
		}
		return response;
	}

	private int _doInBackgroud() throws IOException {
		try {
			this.setUpSocket();
		} catch (IOException e) {
			throw e;
		} catch (Throwable t) {
			Log.e("-", "Setting up: " + t.toString());
		}
		Log.e("-", "[pre-out] " + packetRappresentation);
		printWriter.println(this.packetRappresentation);
		Log.e("-", "[out] " + packetRappresentation);
		printWriter.flush();

		if (requiresResponse)
			return bufferedReader.read();

		return Packet.OK;
	}

	@Override
	protected void onPostExecute(Integer result) {
		this.exitFromApplication();

		Toast toast = Toast.makeText(this.context,
				failureMessage.subSequence(0, failureMessage.length()),
				Toast.LENGTH_LONG);
		toast.show();
	}

	private int handleInvalidPacket() {
		return Packet.UNKNOWN_PACKET;
	}

	private int handleServerUnreachable() {
		return Packet.CONNECTION_ERROR;
	}

	Context getContext() {
		return context;
	}

	void createSharedPreferences(String username, String password,
			rise.comunity.Status status) {
		SharedPreferences userInfo = context.getSharedPreferences(
				"SHARED_PREFS", 0);
		Editor editor = userInfo.edit();
		editor = editor.putString(Splash.usernameKey, username);
		editor = editor.putString(Splash.passwordKey, password);
		editor = editor.putString(Splash.statusKey, status.toString());

		editor.commit();
	}

	void exitFromApplication() {
		socket = null;

		UserData.clearUserData();
		Intent intent = new Intent(context, AccessActivity.class);
		context.startActivity(intent);

		SharedPreferences userInfo = context.getSharedPreferences(
				"SHARED_PREFS", 0);
		Editor editor = userInfo.edit();
		editor.clear();
		editor.commit();

		ReceiverService receiverService = ReceiverService
				.obtainReceiverService();
		if(receiverService != null)
			receiverService.stopService();

		/****/
		Community.clearCommunity();
	}
}
